package clases.exacto;
import interfaces.Heuristica;

import java.io.IOException;
import java.util.ArrayList;

import clases.CasoDePrueba;
import clases.Helper;
import clases.ResultadoCasoDePruebaArrayBinarios;
import clases.Tupla;

public class AlgoritmoExacto implements Heuristica{

	static ArrayList<CasoDePrueba> casosDePrueba = new ArrayList<CasoDePrueba>();

	public ResultadoCasoDePruebaArrayBinarios dameLaSolucionDelCaso(CasoDePrueba casoDePrueba) {

		int clausulasMax = casoDePrueba.cantidadSol;
		int[] binarioAChequear = new int[casoDePrueba.v];
		int[] binarioQueHaceMaxLasClausulas = new int[casoDePrueba.v];
		
		
		//Seteo las variables fijas del binario
		binarioAChequear = setearVariablesFijas(binarioAChequear, casoDePrueba);

		ArrayList<Integer> listaClausulasSatisfechas = new ArrayList<Integer>();
		
		int cantSeteados = contarCantidadSeteados(casoDePrueba.seteados);
		
		boolean hiceVerdaderasTodasLasClausulas = false;
		int potenciaDeDos = (int)Math.pow(2, new Double(casoDePrueba.v - cantSeteados ));
		for (int i = 0; i < potenciaDeDos && !hiceVerdaderasTodasLasClausulas; i++) {

			sumaBinaria(casoDePrueba, binarioAChequear);
			
			Tupla clausulasSatisfechas = Helper.chequear(binarioAChequear, casoDePrueba);

			if (clausulasSatisfechas.clausulasSatisfechas > clausulasMax) {
				clausulasMax = clausulasSatisfechas.clausulasSatisfechas;
				binarioQueHaceMaxLasClausulas = binarioAChequear.clone();
				listaClausulasSatisfechas = clausulasSatisfechas.listaClausulas;
				
				if (casoDePrueba.c == clausulasMax) {
					hiceVerdaderasTodasLasClausulas = true;
				}
			}
		}
		return new ResultadoCasoDePruebaArrayBinarios(clausulasMax, binarioQueHaceMaxLasClausulas, listaClausulasSatisfechas);
	}

	/**
	 * @param casoDePrueba
	 * @param binarioAChequear
	 */
	private void sumaBinaria(CasoDePrueba casoDePrueba, int[] binarioAChequear) {
		boolean carry = true;
		for (int j = 0; j < binarioAChequear.length && carry; j++) {
			if(casoDePrueba.seteados[j] == 0){					
				if(binarioAChequear[j] == 0){
					binarioAChequear[j] = 1;
					carry = false;
				} else {
					binarioAChequear[j] = 0;
				}					
			}
		}
	}

	private int contarCantidadSeteados(int[] seteados) {
		int res = 0;
		for (int i = 0; i < seteados.length; i++) {
			if(seteados[i] > 0){
				res++;
			}
		}
		return res;
	}

	private int[] setearVariablesFijas(int[] binarioQueHaceMaxLasClausulas, CasoDePrueba casoDePrueba) {
		for (int i = 0; i < casoDePrueba.v; i++) {
			//Si son distintos y ambos no son mayores a 0, o sea, uno es 0 y el otro no seteo en 1 el que me indica y lo dejo fijo
			if(casoDePrueba.negativos[i] > 0){
				if(casoDePrueba.positivos[i] == 0){
					casoDePrueba.seteados[i]=1;
					binarioQueHaceMaxLasClausulas[i]=0;
				}
			} else if (casoDePrueba.positivos[i] > 0){
				casoDePrueba.seteados[i]=1;
				binarioQueHaceMaxLasClausulas[i]=1;
			}
		}
		return binarioQueHaceMaxLasClausulas;
	}

	public static void main(String[] args) throws IOException {
		AlgoritmoExacto ae = new AlgoritmoExacto();
		ae.doit();
	}

	public void doit() throws IOException {
		
		Helper.leerArchivo(this,"TP3Exacto.out");
		
		
	}
}
